﻿#include "klinewidget.h"
#include <QOpenGLContext>
#include <QOpenGLShader>
#include <QDebug>
#include <QVector>

KLineWidget::KLineWidget(QWidget *parent)
    : QOpenGLWidget(parent), m_program(nullptr), m_width(800), m_height(600), m_initialized(false)
{
}

KLineWidget::~KLineWidget()
{
    if (m_program) {
        delete m_program;
    }
}

void KLineWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    setupShaders();
    setupBuffers();

    m_initialized = true; // 标记 OpenGL 已初始化
}

void KLineWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if (m_klineData.isEmpty()) {
        return;
    }

    m_program->bind();
    m_vao.bind();
    m_ibo.bind();

    // 绘制 K 线
    glDrawElements(GL_LINES, m_klineData.size() * 8, GL_UNSIGNED_INT, 0);

    m_ibo.release();
    m_vao.release();
    m_program->release();
}

void KLineWidget::resizeGL(int width, int height)
{
    m_width = width;
    m_height = height;
    glViewport(0, 0, width, height);
}

void KLineWidget::setupShaders()
{
    m_program = new QOpenGLShaderProgram(this);

    const char *vertexShaderSource = R"(
        #version 330 core
        layout (location = 0) in vec2 position;
        uniform float width;
        uniform float height;
        uniform float minY;
        uniform float maxY;
        void main() {
            float x = (position.x / width) * 2.0 - 1.0;
            float y = (position.y / height) * 2.0 - 1.0;
            y = (y - minY) / (maxY - minY) * 2.0 - 1.0;
            gl_Position = vec4(x, y, 0.0, 1.0);
        }
    )";

    const char *fragmentShaderSource = R"(
        #version 330 core
        out vec4 FragColor;
        void main() {
            FragColor = vec4(1.0, 0.5, 0.2, 1.0);
        }
    )";

    if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource)) {
        qDebug() << "Failed to compile vertex shader:" << m_program->log();
    }

    if (!m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource)) {
        qDebug() << "Failed to compile fragment shader:" << m_program->log();
    }

    if (!m_program->link()) {
        qDebug() << "Failed to link shader program:" << m_program->log();
    }
}

void KLineWidget::setupBuffers()
{
    // 确保在 OpenGL 上下文激活的情况下创建和绑定资源
    m_vao.create();
    m_vbo.create();
    m_ibo.create();

    m_vao.bind();
    m_vbo.bind();

    QVector<float> vertices;
    QVector<GLuint> indices;

    float minY = static_cast<float>(m_klineData[0].lowPrice);
    float maxY = static_cast<float>(m_klineData[0].highPrice);

    for (const KLineData &kline : m_klineData) {
        if (kline.lowPrice < minY) minY = static_cast<float>(kline.lowPrice);
        if (kline.highPrice > maxY) maxY = static_cast<float>(kline.highPrice);
    }

    for (int i = 0; i < m_klineData.size(); ++i) {
        const KLineData &kline = m_klineData[i];
        float x = i * 1.5f;
        float y1 = static_cast<float>(kline.openPrice);
        float y2 = static_cast<float>(kline.closePrice);
        float y3 = static_cast<float>(kline.highPrice);
        float y4 = static_cast<float>(kline.lowPrice);

        // K线主体
        vertices << x - 0.2f << y1;
        vertices << x - 0.2f << y2;
        vertices << x + 0.2f << y2;
        vertices << x + 0.2f << y1;

        // K线上影线
        vertices << x << y3;
        vertices << x << y2;

        // K线下影线
        vertices << x << y1;
        vertices << x << y4;

        // 索引
        indices << i * 8 + 0 << i * 8 + 1;
        indices << i * 8 + 1 << i * 8 + 2;
        indices << i * 8 + 2 << i * 8 + 3;
        indices << i * 8 + 4 << i * 8 + 5;
        indices << i * 8 + 6 << i * 8 + 7;
    }

    m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(float));
    m_ibo.allocate(indices.constData(), indices.size() * sizeof(GLuint));

    m_program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 2 * sizeof(float));
    m_program->enableAttributeArray(0);

    m_vao.release();
    m_vbo.release();
    m_ibo.bind();

    // 设置统一变量
    m_program->bind();
    m_program->setUniformValue("width", static_cast<GLfloat>(m_width));
    m_program->setUniformValue("height", static_cast<GLfloat>(m_height));
    m_program->setUniformValue("minY", minY);
    m_program->setUniformValue("maxY", maxY);
    m_program->release();
}

void KLineWidget::setKLineData(const QVector<KLineData> &data)
{
    m_klineData = data;

    // 如果 OpenGL 尚未初始化，则初始化
    if (m_initialized) {
        makeCurrent(); // 确保当前上下文激活
        setupBuffers(); // 重新设置缓冲区数据
        doneCurrent(); // 完成当前上下文的操作
    }
    update(); // 触发重绘
}